#ifndef CONTOUR
#define CONTOUR

#include "point.h"
#include <vector>
#include <iostream>
#include <numeric>

struct contour_t;

typedef std::vector<point_t> contour_data_t;

point_t top_left_corner(contour_data_t const & vertices);
point_t bottom_right_corner(contour_data_t const & vertices);
point_t * find(point_t const & point, contour_data_t & vertices);

contour_t get_contour(contour_data_t const & vertices);

std::ostream & operator<<(std::ostream & out, contour_data_t const & vertices);
std::istream & operator>>(std::istream & in, contour_data_t & vertices);


struct leftmost
{
    point_t const & operator() (point_t const & l, point_t const & r) const;
};

struct rightmost
{
    point_t const & operator() (point_t const & l, point_t const & r) const;
};

enum direction_t
{
    CLOCKWISE,
    COUNTERCLOCKWISE
};

struct contour_t
{
    contour_t();

    template <class FwdIter>
       contour_t(FwdIter p, FwdIter q)
          : vertices_(p, q)
    {
        if(p != q)
        {
            left_point_ = std::accumulate(p, q, *p, leftmost());
            right_point_ = std::accumulate(p, q, *p, rightmost());
        }
    }

    void add(point_t const & point);

    point_t const & operator [](size_t index) const;
    point_t const & left_point () const;
    point_t const & right_point () const;

    bool empty() const;
    size_t size() const;

    void direction(direction_t new_direction);
    direction_t direction() const;

    friend std::ostream & operator<<(std::ostream & out, contour_t const & contour);
    friend std::istream & operator>>(std::istream & in, contour_t & contour);

private:
    std::vector<point_t> vertices_;
    point_t left_point_;
    point_t right_point_;
};

#endif
